package com.zjgsu.nftplatform.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.*;
import com.auth0.jwt.interfaces.JWTVerifier;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.Calendar;

/**
 * @author ahy231
 * @date 2021/7/23 13:31
 * @description JWT 工具类
 */
@Component
public class JWTUtil {

    // 过期时间为 24 个小时
    @Value("${jwt.expire-time}")
    private int EXPIRE_TIME;
    // 密钥
    @Value("${jwt.secret}")
    private String SECRET;

    /**
     * 生成 token
     */
    public String createToken(long userId) {
        Calendar deadline = Calendar.getInstance();
        deadline.setTimeInMillis(System.currentTimeMillis());
        deadline.add(Calendar.MILLISECOND, EXPIRE_TIME);

        Algorithm algorithm = Algorithm.HMAC256(SECRET);

        return JWT.create()
                .withClaim("userId", userId)
                .withExpiresAt(deadline.getTime())
                .sign(algorithm);
    }

    /**
     * 验证 token 是否合法
     */
    public boolean verify(String token, long userId) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim("userId", userId)
                    .build();
            verifier.verify(token);
            return true;
        } catch (AlgorithmMismatchException | SignatureVerificationException | TokenExpiredException | InvalidClaimException | JWTDecodeException e) {
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 从 token 中获取 userId
     */
    public static Long getUserId(String token) {
        try {
            return JWT.decode(token).getClaim("userId").asLong();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * service层获取用户id
     * @return 用户id
     */
    public static Long serviceGetUserId() {
        Long userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
        Assert.notNull(userId, "service 获取不到用户 id");
        return userId;
    }
}
